<template>
  <el-popover
    width="200"
    trigger="click"
  >
    <template #reference>
      <el-button
        icon="el-icon-s-tools"
        type="primary"
        size="small"
      >
        列设置
      </el-button>
    </template>

    <div
      class="v-table__column-setting"
      :class="{ 'sorting': elIndex !== null }"
      @mousedown="onMouseDown"
      @mousemove="onMouseMove"
    >
      <div
        ref="items"
        class="column-item"
        v-for="(item, index) in tableColumns"
        :key="item.options.prop"
        :data-index="index"
      >
        <el-checkbox :value="item.show" @input="handleToggle(item)">
          {{ item.options.label }}
        </el-checkbox>
        <i
          class="el-icon el-icon-sort"
          :class="{ 'active': index === elIndex }"
          @mousedown="setSorting(index)"
        />
      </div>
    </div>
  </el-popover>
</template>

<script>
import { useTableSettingRecord } from './tableSettingRecord'

const getIndex = (el) => el && el.dataset && +el.dataset.index

export default {
  props: {
    columns: {
      type: Array,
      required: true
    },
    name: {
      type: String,
      required: true
    }
  },

  data() {
    return {
      isSorting: false,
      startY: 0,
      elIndex: null
    }
  },

  computed: {
    tableColumns() {
      return this.columns.filter(col => (
        !col.options.type &&
        col.options.label &&
        !col.options.fixed
      ))
    }
  },

  mounted() {
    document.addEventListener('mouseup', this.onMouseUp)
  },

  beforeDestroy() {
    document.removeEventListener('mouseup', this.onMouseUp)
  },

  methods: {
    handleToggle(item) {
      item.show = !item.show
      this.saveAndUpdate(this.columns, 'isShow')
    },
    handleSort(targetIndex, isBefore) {
      const column = this.tableColumns[this.elIndex]
      const columns = this.columns.filter(col => col !== column)

      const target = this.tableColumns[targetIndex]
      const index = columns.indexOf(target)

      columns.splice(isBefore ? index : index + 1, 0, column)
      this.saveAndUpdate(columns, 'sort')
    },
    saveAndUpdate(columns, type) {
      const { setRecord } = useTableSettingRecord(this.name)
      setRecord(type, columns.reduce((res, col, index) => {
        if (type === 'isShow') {
          res[col.options.prop] = col.show
        } else if (type === 'sort') {
          res[col.options.prop] = index
        }
        return res
      }, {}))

      this.$emit('update:columns', columns)
    },
    setSorting(index) {
      if (!this.isSorting) {
        this.isSorting = true
        this.elIndex = index
      }
    },
    onMouseDown(e) {
      this.startY = e.clientY
    },
    onMouseMove(e) {
      if (this.isSorting) {
        const itemEl = e.path.find(el => el.classList.contains('column-item'))
        this.$refs.items.forEach((el) => {
          el.classList.remove('border-bottom')
          el.classList.remove('border-top')
          if (el === itemEl && getIndex(el) !== this.elIndex) {
            el.classList.add(e.clientY < this.startY ? 'border-top' : 'border-bottom')
          }
        })
      }
    },
    onMouseUp(e) {
      const itemEl = e.path.find(el => {
        return el.classList && el.classList.contains('column-item')
      })
      if (itemEl) {
        const isUp = itemEl.classList.contains('border-top')
        const isDown = itemEl.classList.contains('border-bottom')
        if (isUp || isDown) {
          this.handleSort(getIndex(itemEl), isUp)
        }
      }

      this.$refs.items.forEach(el => {
        el.classList.remove('border-bottom')
        el.classList.remove('border-top')
      })
      this.isSorting = false
      this.elIndex = null
    }
  }
}
</script>

<style lang="less" scoped>
.v-table__column-setting {
  user-select: none;

  &.sorting {
    cursor: move;
  }

  .column-item {
    display: flex;
    align-items: center;
    padding: 2px 0;

    &.border-top {
      border-top: 1px dashed;
    }

    &.border-bottom {
      border-bottom: 1px dashed;
    }

    .el-icon {
      cursor: move;
      margin-left: auto;
      color: #888888;
      font-size: 15px;

      &.active {
        color: #2196f3;
      }
    }
  }
}
</style>